package club.vann.kafka.mock.controller;

import club.vann.kafka.mock.common.http.HttpResponse;
import club.vann.kafka.mock.common.http.HttpStatus;
import club.vann.kafka.mock.common.model.csv.CsvTable;
import club.vann.kafka.mock.common.model.enums.FileType;
import club.vann.kafka.mock.common.model.info.DynamicTablePage;
import club.vann.kafka.mock.util.CsvUtil;
import club.vann.kafka.mock.util.StringUtil;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.Collections;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ObjectUtils;

/** 定义Controller基类。 */
public class BaseController {
  /**
   * 返回成功信息。
   *
   * <p>注意：Http协议状态：200，前后端响应状态：SUCCESS
   *
   * @param message 提示信息
   * @return 返回响应信息
   */
  public ResponseEntity<HttpResponse> success(String message) {
    return success(Collections.emptyList(), message);
  }

  /**
   * 返回成功信息。
   *
   * <p>注意：Http协议状态：200，前后端响应状态：SUCCESS
   *
   * @param pageData 返回数据
   * @param message 提示信息
   * @return 返回响应信息
   */
  public ResponseEntity<HttpResponse> success(Page<?> pageData, String message) {
    return success(
        pageData.getContent(),
        message,
        pageData.getPageable().getPageNumber() + 1,
        pageData.getPageable().getPageSize(),
        pageData.getTotalElements());
  }

  /**
   * 返回成功信息。
   *
   * <p>注意：Http协议状态：200，前后端响应状态：SUCCESS
   *
   * @param collection 返回数据
   * @param message 提示信息
   * @return 返回响应信息
   */
  public ResponseEntity<HttpResponse> success(
      Collection<? extends Object> collection, String message) {
    if (ObjectUtils.isEmpty(collection)) {
      return success(Collections.emptyList(), message, 1, 1, 0L);
    }
    return success(collection, message, 1, collection.size(), (long) (collection.size()));
  }

  /**
   * 返回成功信息。
   *
   * <p>注意：Http协议状态：200，前后端响应状态：SUCCESS
   *
   * @param data 返回数据
   * @param message 提示信息
   * @return 返回响应信息
   */
  public ResponseEntity<HttpResponse> success(Object data, String message) {
    return success(data, message, 1, 1, 1L);
  }

  /**
   * 返回成功信息。
   *
   * <p>注意：Http协议状态：200，前后端响应状态：SUCCESS
   *
   * @param dynamicTablePage 返回数据
   * @param message 提示信息
   * @return 返回响应信息
   */
  public ResponseEntity<HttpResponse> success(DynamicTablePage dynamicTablePage, String message) {
    return success(
        dynamicTablePage.getDynamicTableInfo(),
        message,
        dynamicTablePage.getCurPage() + 1,
        dynamicTablePage.getPageSize(),
        dynamicTablePage.getTotal());
  }

  /**
   * 返回成功信息（包含分页数据）。
   *
   * <p>注意：Http协议状态：200，前后端响应状态：SUCCESS
   *
   * @param data 数据
   * @param message 提示信息
   * @param curPage 当前页
   * @param pageSize 每页容量
   * @param total 总数据量
   * @return 返回响应信息
   */
  public ResponseEntity<HttpResponse> success(
      Object data, String message, Integer curPage, Integer pageSize, Long total) {
    return responseResponse(
        org.springframework.http.HttpStatus.OK,
        data,
        message,
        HttpStatus.success,
        curPage,
        pageSize,
        total);
  }

  /**
   * 返回警告信息。
   *
   * <p>注意：Http协议状态：200，前后端响应状态：WARN
   *
   * @param message 提示信息
   * @return 返回响应信息
   */
  public ResponseEntity<HttpResponse> warn(String message) {
    return responseResponse(
        org.springframework.http.HttpStatus.OK, null, message, HttpStatus.warn, 1, 1, 1L);
  }

  /**
   * 返回失败信息。
   *
   * <p>注意：Http协议状态：400，前后端响应状态：ERROR
   *
   * @param message 提示信息
   * @return 返回响应信息
   */
  public ResponseEntity<HttpResponse> fail(String message) {
    return fail(org.springframework.http.HttpStatus.BAD_REQUEST, message);
  }

  /**
   * 返回失败信息。
   *
   * <p>注意：Http协议状态：自定义，前后端响应状态：ERROR
   *
   * @param status Http协议状态
   * @param message 提示信息
   * @return 返回响应信息
   */
  public ResponseEntity<HttpResponse> fail(
      org.springframework.http.HttpStatus status, String message) {
    return responseResponse(status, null, message, HttpStatus.error, 1, 1, 1L);
  }

  public ResponseEntity<byte[]> download(String fileName, String fileData)
      throws UnsupportedEncodingException {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    headers.set(
        "Content-Disposition",
        "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
    return ResponseEntity.ok().headers(headers).body(fileData.getBytes("GB18030"));
  }

  /**
   * 下载CSV文件。
   *
   * @param fileName 文件名
   * @param fileType 文件类型
   * @param csvTable csv格式数据
   * @return CSV数据流
   */
  public ResponseEntity<byte[]> download(String fileName, FileType fileType, CsvTable csvTable) {
    final String fileNameWithTime =
        String.join(
            StringUtil.MID_DELIMITER,
            fileName,
            LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")));
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    headers.set(
        "Content-Disposition",
        "attachment;filename="
            + URLEncoder.encode(
                fileNameWithTime + "." + fileType.getKey(), StandardCharsets.UTF_8));
    return ResponseEntity.ok().headers(headers).body(CsvUtil.wirter(csvTable));
  }

  /**
   * @param status Http协议响应状态
   * @param data 数据
   * @param message 提示信息
   * @param httpStatus 前后端响应状态
   * @param curPage 当前页
   * @param pageSize 每页容量
   * @param total 数据总量
   * @return ResponseEntity
   */
  private ResponseEntity<HttpResponse> responseResponse(
      org.springframework.http.HttpStatus status,
      Object data,
      String message,
      HttpStatus httpStatus,
      Integer curPage,
      Integer pageSize,
      Long total) {
    HttpResponse httpResponse = new HttpResponse();
    httpResponse.setStatus(httpStatus);
    httpResponse.setData(data);
    httpResponse.setMessage(message);
    httpResponse.setPageInfo(curPage, pageSize, total);
    return ResponseEntity.status(status).body(httpResponse);
  }
}
